// 智能建议生成器
use crate::errors::{CompilerError, ErrorKind, RuntimeError};

/// 智能建议生成器
pub struct SuggestionGenerator;

impl SuggestionGenerator {
    /// 根据错误类型和上下文生成修复建议
    pub fn generate_suggestion(error_kind: ErrorKind, context: &str) -> Option<String> {
        match error_kind {
            // 词法分析错误
            ErrorKind::LexicalError => Some("请检查代码中是否有非法字符或拼写错误".to_string()),
            ErrorKind::UnterminatedString => Some("请为字符串添加闭合引号".to_string()),
            ErrorKind::InvalidNumberFormat => Some("请检查数字格式是否正确".to_string()),
            ErrorKind::InvalidIdentifier => Some("请检查标识符命名是否符合规范".to_string()),
            ErrorKind::UnterminatedComment => Some("请为注释添加闭合标记".to_string()),

            // 语法分析错误
            ErrorKind::SyntaxError => Self::suggest_syntax_error(context),
            ErrorKind::UnexpectedToken => Self::suggest_unexpected_token(context),
            ErrorKind::MissingToken => Self::suggest_missing_token(context),
            ErrorKind::UnbalancedBrackets => Self::suggest_unbalanced_brackets(context),
            ErrorKind::InvalidStatement => Some("请检查语句格式是否正确".to_string()),
            ErrorKind::UnexpectedEOF => Some("程序意外结束，请检查是否有未闭合的结构".to_string()),
            ErrorKind::InvalidIndentation => Some("请检查代码缩进是否一致".to_string()),

            // 语义分析错误
            ErrorKind::SemanticError => Some("语义错误，请检查代码的逻辑正确性".to_string()),
            ErrorKind::UndefinedIdentifier => Self::suggest_undefined_identifier(context),
            ErrorKind::AlreadyDefined => Some("该标识符已被定义，请使用其他名称".to_string()),
            ErrorKind::TypeMismatch => Self::suggest_type_mismatch(context),
            ErrorKind::ArgumentMismatch => Self::suggest_argument_mismatch(context),
            ErrorKind::InvalidType => Some("无效的类型，请检查类型定义".to_string()),
            ErrorKind::InvalidFunctionCall => {
                Some("无效的函数调用，请检查函数名和参数".to_string())
            }
            ErrorKind::UndefinedFunction => {
                Some("未定义的函数，请检查函数名拼写或确保函数已定义".to_string())
            }
            ErrorKind::InvalidAssignment => Some("无效的赋值操作，请检查赋值目标".to_string()),
            ErrorKind::OutOfScope => {
                Some("变量超出作用域，请确保在正确的作用域内使用变量".to_string())
            }
            ErrorKind::ConstantReassignment => {
                Some("常量不能重新赋值，请使用变量或选择其他名称".to_string())
            }
            ErrorKind::InvalidInheritance => {
                Some("无效的继承关系，请检查父类是否存在或可继承".to_string())
            }
            ErrorKind::InterfaceNotImplemented => {
                Some("接口未完全实现，请确保实现了所有必要的方法".to_string())
            }
            ErrorKind::GenericError => Some("泛型相关错误，请检查泛型参数和约束".to_string()),
            ErrorKind::InvalidOverride => {
                Some("无效的方法重写，请检查方法签名是否与父类匹配".to_string())
            }
            ErrorKind::AccessControlError => {
                Some("访问控制错误，请检查访问修饰符和权限".to_string())
            }

            // 运行时错误
            ErrorKind::RuntimeError => Some("运行时错误，请检查程序逻辑".to_string()),
            ErrorKind::IndexOutOfBounds => {
                Some("数组索引越界，请检查索引值是否在有效范围内".to_string())
            }
            ErrorKind::DivisionByZero => Some("除数不能为零，请检查除数表达式".to_string()),
            ErrorKind::NullReference => Some("空引用错误，请确保对象已正确初始化".to_string()),
            ErrorKind::InvalidOperation => Some("无效的操作，请检查操作数类型".to_string()),
            ErrorKind::StackOverflow => Some("栈溢出错误，可能存在无限递归".to_string()),
            ErrorKind::RecursionDepthExceeded => {
                Some("递归深度超过限制，请优化递归算法或增加递归深度限制".to_string())
            }
            ErrorKind::FileNotFound => Some("文件未找到，请检查文件路径是否正确".to_string()),
            ErrorKind::PermissionDenied => {
                Some("权限被拒绝，请检查文件或目录的访问权限".to_string())
            }
            ErrorKind::Timeout => Some("操作超时，请优化程序性能或增加超时限制".to_string()),

            // 模块和导入错误
            ErrorKind::ImportError => Some("导入错误，请检查模块路径和内容".to_string()),
            ErrorKind::ModuleNotFound => Some("模块未找到，请检查模块路径是否正确".to_string()),
            ErrorKind::ExportError => Some("导出错误，请检查导出语句格式".to_string()),
            ErrorKind::CircularImport => Some("循环导入错误，请重构模块依赖关系".to_string()),
            ErrorKind::InvalidModule => Some("无效的模块，请检查模块结构和内容".to_string()),
            ErrorKind::ModuleVersionMismatch => {
                Some("模块版本不匹配，请使用兼容的模块版本".to_string())
            }
            ErrorKind::MissingExport => {
                Some("缺少导出符号，请检查模块是否导出了该符号".to_string())
            }

            // IO 错误
            ErrorKind::IOError => Some("IO错误，请检查文件操作权限和路径".to_string()),
            ErrorKind::ReadError => Some("读取错误，请检查文件是否存在且可读取".to_string()),
            ErrorKind::WriteError => Some("写入错误，请检查文件是否可写".to_string()),
            ErrorKind::FileExists => Some("文件已存在，请选择其他文件名或路径".to_string()),
            ErrorKind::InvalidPath => Some("无效的路径，请检查路径格式是否正确".to_string()),
            ErrorKind::DirectoryError => Some("目录错误，请检查目录是否存在且可访问".to_string()),
            ErrorKind::EncodingError => Some("编码错误，请检查文件编码是否正确".to_string()),

            // 警告和信息错误
            ErrorKind::DeprecatedFeature => Some("此特性已过时，建议使用替代方案".to_string()),
            ErrorKind::UnusedVariable => Some("变量未使用，建议删除或使用该变量".to_string()),
            ErrorKind::UnusedImport => Some("导入未使用，建议删除该导入".to_string()),
            ErrorKind::UnreachableCode => Some("代码不可达，建议删除或修复条件判断".to_string()),
            ErrorKind::UnusedFunction => Some("函数未使用，建议删除或使用该函数".to_string()),
            ErrorKind::ShadowingVariable => {
                Some("变量被阴影覆盖，建议使用不同的变量名".to_string())
            }
            ErrorKind::PerformanceWarning => Some("此代码可能存在性能问题，建议优化".to_string()),
            ErrorKind::CodeStyleWarning => Some("代码风格不符合规范，建议调整".to_string()),
            ErrorKind::DeprecatedSyntax => Some("此语法已过时，建议使用新语法".to_string()),
            ErrorKind::UnusedParameter => Some("参数未使用，建议删除或使用该参数".to_string()),
            ErrorKind::MissingDocumentation => Some("缺少文档，建议添加文档注释".to_string()),

            // 信息提示
            ErrorKind::InfoMessage => Some("信息提示".to_string()),
            ErrorKind::OptimizationHint => Some("优化建议，可考虑实施".to_string()),
            ErrorKind::VersionInfo => Some("版本信息".to_string()),
            ErrorKind::DebugInfo => Some("调试信息".to_string()),
            ErrorKind::UsageInfo => Some("使用信息".to_string()),
        }
    }

    /// 语法错误建议
    fn suggest_syntax_error(context: &str) -> Option<String> {
        if context.contains("期望") && context.contains("但得到") {
            Some("请检查代码语法是否符合墨言语言规范".to_string())
        } else {
            Some("语法错误，请检查代码格式".to_string())
        }
    }

    /// 意外标记建议
    fn suggest_unexpected_token(context: &str) -> Option<String> {
        if context.contains("期望 Identifier") {
            Some("请检查是否使用了正确的标识符".to_string())
        } else if context.contains("期望 ") {
            let expected = context.split("期望 ").nth(1)?.split(",").next()?;
            Some(format!("请检查是否缺少或使用了正确的{}", expected))
        } else {
            Some("请检查代码中是否有多余或错误的标记".to_string())
        }
    }

    /// 缺少标记建议
    fn suggest_missing_token(context: &str) -> Option<String> {
        if context.contains("期望") {
            let expected = context.split("期望 ").nth(1)?.split(",").next()?;
            Some(format!("请添加缺少的{}", expected))
        } else {
            Some("请检查代码中是否缺少必要的标记".to_string())
        }
    }

    /// 括号不匹配建议
    fn suggest_unbalanced_brackets(context: &str) -> Option<String> {
        if context.contains("右括号") {
            Some("请添加缺失的右括号".to_string())
        } else if context.contains("左括号") {
            Some("请添加缺失的左括号".to_string())
        } else {
            Some("请检查括号是否匹配".to_string())
        }
    }

    /// 未定义标识符建议
    fn suggest_undefined_identifier(context: &str) -> Option<String> {
        if let Some(ident) = context.split("'").nth(1) {
            // 基于常见拼写错误模式的智能建议
            let suggestion = format!("请检查 '{}' 的拼写，或确保它已被定义\n", ident);

            // 添加一些常见的修复建议
            let mut full_suggestion = suggestion;
            full_suggestion += "常见问题：\n";
            full_suggestion += "- 检查大小写是否正确（如变量名区分大小写）\n";
            full_suggestion += "- 检查是否在正确的作用域内定义了该变量\n";
            full_suggestion += "- 检查是否有拼写错误（如漏掉字母或多余字母）\n";
            full_suggestion += "- 检查是否在使用前已经声明并初始化了该变量";

            Some(full_suggestion)
        } else {
            Some("请检查标识符是否已被定义\n常见问题：\n- 检查变量名拼写\n- 检查变量是否在正确的作用域内\n- 检查变量是否在使用前已声明".to_string())
        }
    }

    /// 类型不匹配建议
    fn suggest_type_mismatch(context: &str) -> Option<String> {
        if context.contains("期望") && context.contains("但得到") {
            let expected = context.split("期望 ").nth(1)?.split(",").next()?;
            let found = context.split("但得到 ").nth(1)?.split(",").next()?;
            Some(format!(
                "类型不匹配: 期望 {}, 但得到 {}\n建议: 请确保操作数类型兼容，或添加类型转换",
                expected, found
            ))
        } else {
            Some(
                "类型不匹配\n建议: 请检查表达式的类型是否符合预期，或添加适当的类型转换"
                    .to_string(),
            )
        }
    }

    /// 参数不匹配建议
    fn suggest_argument_mismatch(context: &str) -> Option<String> {
        if context.contains("期望") && context.contains("但得到") {
            let expected = context.split("期望 ").nth(1)?.split(" ").next()?;
            let found = context.split("但得到 ").nth(1)?.split(" ").next()?;
            Some(format!(
                "参数数量不匹配: 期望 {} 个参数, 但得到 {} 个\n建议: 请检查函数调用的参数数量是否正确",
                expected, found
            ))
        } else {
            Some(
                "参数数量不匹配\n建议: 请检查函数调用的参数数量和类型是否与函数定义一致"
                    .to_string(),
            )
        }
    }

    /// 生成基于常见错误模式的智能建议
    pub fn generate_pattern_based_suggestion(error_message: &str) -> Option<String> {
        // 常见错误模式和建议
        let patterns = [
            // 变量相关错误
            (
                "未定义的标识符",
                "请检查变量名拼写或确保变量已定义\n常见问题：\n- 检查大小写是否正确\n- 检查作用域范围\n- 检查拼写错误\n- 检查是否在使用前声明",
            ),
            (
                "已定义",
                "请使用其他名称或删除重复定义\n建议：\n- 重命名新变量\n- 删除重复定义\n- 检查变量作用域",
            ),
            (
                "超出作用域",
                "请确保在正确的作用域内使用变量\n建议：\n- 将变量定义移到使用它的作用域内\n- 使用适当的作用域嵌套\n- 检查变量声明位置",
            ),
            (
                "常量重新赋值",
                "请使用变量或选择其他名称\n建议：\n- 使用 'let' 代替 'const' 声明可修改的变量\n- 选择不同的变量名\n- 检查是否确实需要修改该值",
            ),
            // 类型相关错误
            (
                "类型不匹配",
                "请确保操作数类型兼容\n建议：\n- 检查表达式的类型是否符合预期\n- 添加适当的类型转换\n- 确保操作数类型支持该操作\n- 检查函数返回类型",
            ),
            (
                "期望",
                "请检查表达式的类型是否符合预期\n建议：\n- 查看相关函数或变量的类型定义\n- 添加类型转换\n- 检查赋值操作的两边类型",
            ),
            (
                "无效的类型",
                "请检查类型定义是否正确\n建议：\n- 确保使用了正确的类型名称\n- 检查类型定义语法\n- 确保类型已被正确导入或定义",
            ),
            // 函数调用相关错误
            (
                "参数数量不匹配",
                "请检查函数调用的参数数量\n建议：\n- 查看函数定义的参数列表\n- 确保提供了所有必需参数\n- 不要提供多余的参数\n- 检查参数顺序是否正确",
            ),
            (
                "无效的函数调用",
                "请检查函数名和参数是否正确\n建议：\n- 检查函数名拼写\n- 检查参数数量和类型\n- 确保函数已被正确定义\n- 检查函数是否在当前作用域内",
            ),
            (
                "未定义的函数",
                "请检查函数名拼写或确保函数已定义\n建议：\n- 检查函数名大小写和拼写\n- 确保函数已被定义\n- 检查函数是否在正确的作用域内\n- 检查函数是否已被正确导入",
            ),
            // 数组相关错误
            (
                "数组索引越界",
                "请检查数组索引是否在有效范围内\n建议：\n- 确保索引值在 0 到数组长度-1 之间\n- 添加索引范围检查\n- 检查数组是否为空\n- 避免硬编码索引值",
            ),
            (
                "索引",
                "请确保索引是有效的整数\n建议：\n- 使用整数类型作为索引\n- 确保索引值非负\n- 检查索引计算是否正确",
            ),
            // 操作符相关错误
            (
                "除以零",
                "请添加除数不为零的检查\n建议：\n- 在除法操作前检查除数是否为零\n- 使用条件语句处理除数为零的情况\n- 考虑使用安全除法函数",
            ),
            (
                "无效的操作",
                "请检查操作数类型是否支持该操作\n建议：\n- 确保操作数类型兼容\n- 检查操作符是否适用于该类型\n- 添加适当的类型转换\n- 考虑使用其他操作符或方法",
            ),
            // 文件相关错误
            (
                "无法读取文件",
                "请检查文件路径是否正确\n建议：\n- 检查文件路径拼写\n- 确保文件存在\n- 检查文件访问权限\n- 确保路径格式正确",
            ),
            (
                "文件未找到",
                "请检查文件是否存在\n建议：\n- 检查文件路径是否正确\n- 确保文件已创建\n- 检查文件是否被移动或删除\n- 检查文件权限",
            ),
            (
                "权限被拒绝",
                "请检查文件访问权限\n建议：\n- 确保程序有读取/写入文件的权限\n- 检查文件所有权\n- 尝试使用管理员权限运行\n- 检查文件是否被其他程序锁定",
            ),
            // 语法相关错误
            (
                "意外的标记",
                "请检查代码中是否有多余或错误的标记\n建议：\n- 检查代码语法\n- 移除多余的标点符号\n- 检查标记拼写\n- 确保标记使用正确",
            ),
            (
                "缺少",
                "请添加缺少的标记\n建议：\n- 检查代码语法\n- 添加缺少的标点符号\n- 确保所有结构都已正确闭合\n- 检查语句是否完整",
            ),
            (
                "括号不匹配",
                "请检查括号是否匹配\n建议：\n- 确保所有括号都有对应的闭合括号\n- 检查括号类型是否正确（圆括号、方括号、花括号）\n- 使用缩进帮助匹配括号\n- 考虑使用代码编辑器的括号匹配功能",
            ),
            (
                "字符串未闭合",
                "请为字符串添加闭合引号\n建议：\n- 为字符串添加缺失的引号\n- 检查字符串中是否有未转义的引号\n- 考虑使用多行字符串语法",
            ),
            (
                "注释未闭合",
                "请为注释添加闭合标记\n建议：\n- 为注释添加缺失的闭合标记\n- 检查注释语法是否正确\n- 考虑使用单行注释代替多行注释",
            ),
            (
                "无效的缩进",
                "请检查代码缩进是否一致\n建议：\n- 使用统一的缩进风格（空格或制表符）\n- 确保缩进级别正确\n- 检查代码块的缩进是否一致\n- 使用代码编辑器的自动缩进功能",
            ),
            (
                "意外的文件结束",
                "请检查是否有未闭合的结构\n建议：\n- 检查是否有未闭合的括号、引号或注释\n- 确保所有代码块都已正确闭合\n- 检查文件是否完整",
            ),
            // 模块相关错误
            (
                "导入错误",
                "请检查模块路径和内容\n建议：\n- 检查模块路径拼写\n- 确保模块存在\n- 检查模块内容是否有语法错误\n- 检查模块导出是否正确",
            ),
            (
                "模块未找到",
                "请检查模块路径是否正确\n建议：\n- 检查模块路径拼写\n- 确保模块存在于正确的位置\n- 检查模块搜索路径\n- 确保模块已被正确安装",
            ),
            (
                "循环导入",
                "请重构模块依赖关系\n建议：\n- 重构代码以消除循环依赖\n- 使用延迟导入\n- 考虑将共享代码提取到独立模块\n- 重新组织模块结构",
            ),
            (
                "缺少导出",
                "请检查模块是否导出了该符号\n建议：\n- 检查模块的导出语句\n- 确保符号被正确导出\n- 检查符号名称拼写\n- 确保符号在模块中已被定义",
            ),
        ];

        for (pattern, suggestion) in &patterns {
            if error_message.contains(pattern) {
                return Some(suggestion.to_string());
            }
        }

        None
    }
}

/// 辅助函数：生成编译器错误的智能建议
pub fn generate_compiler_suggestion(error: &CompilerError) -> Option<String> {
    SuggestionGenerator::generate_suggestion(error.kind.clone(), &error.message)
}

/// 辅助函数：生成运行时错误的智能建议
pub fn generate_runtime_suggestion(error: &RuntimeError) -> Option<String> {
    SuggestionGenerator::generate_suggestion(error.kind.clone(), &error.message)
}

/// 辅助函数：生成基于错误消息的智能建议
pub fn generate_suggestion_from_message(error_message: &str) -> Option<String> {
    SuggestionGenerator::generate_pattern_based_suggestion(error_message)
}
